#!/bin/bash
###############################################################################
#       脚本名称: log_context.sh
#       功能描述: 上下文管理模块,管理日志的上下文信息。
#       作者: 林再来
#       日期: 2025-10-14
#       版本: 1.0
#       功能:
#           1、追踪ID管理(trace_id)
#           2、会话ID管理(session_id)
#           3、请求ID管理(request_id)
#           4、自定义上下文字段
#           5、上下文继承和传递
#       依赖(插件/命令):
#           无
###############################################################################

# 防止重复加载
[[ -n "${_LOG_CONTEXT_LOADED:-}" ]] && return 0
readonly _LOG_CONTEXT_LOADED=1

#-----------------------------------------------------------------------------
# 全局变量
#-----------------------------------------------------------------------------
# 上下文数据存储
declare -gA _LOG_CONTEXT_DATA

#-----------------------------------------------------------------------------
# 函数: 初始化上下文
# 参数: 无
# 返回: 0-成功
#-----------------------------------------------------------------------------
function _log_context_init() {
    # 清空现有上下文
    _LOG_CONTEXT_DATA=()
    
    # 设置默认值
    _LOG_CONTEXT_DATA["pid"]="$$"
    _LOG_CONTEXT_DATA["ppid"]="$PPID"
    _LOG_CONTEXT_DATA["hostname"]="${HOSTNAME:-$(hostname 2>/dev/null || echo 'unknown')}"
    _LOG_CONTEXT_DATA["username"]="${USER:-$(whoami 2>/dev/null || echo 'unknown')}"
    
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 设置上下文变量
# 参数: $1 - 键名
#       $2 - 键值
# 返回: 0-成功
#-----------------------------------------------------------------------------
function log_context_set() {
    local key="$1"
    local value="$2"
    
    _LOG_CONTEXT_DATA["$key"]="$value"
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 获取上下文变量
# 参数: $1 - 键名
#       $2 - 默认值(可选)
# 返回: 输出键值,不存在则返回默认值
#-----------------------------------------------------------------------------
function log_context_get() {
    local key="$1"
    local default="${2:-}"
    
    if [[ -n "${_LOG_CONTEXT_DATA[$key]:-}" ]]; then
        echo "${_LOG_CONTEXT_DATA[$key]}"
    else
        echo "$default"
    fi
}

#-----------------------------------------------------------------------------
# 函数: 删除上下文变量
# 参数: $1 - 键名
# 返回: 0-成功
#-----------------------------------------------------------------------------
function log_context_unset() {
    local key="$1"
    unset _LOG_CONTEXT_DATA["$key"]
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 清除所有上下文
# 参数: 无
# 返回: 0-成功
#-----------------------------------------------------------------------------
function log_context_clear() {
    _log_context_init
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 设置追踪ID
# 参数: $1 - 追踪ID
# 返回: 0-成功
#-----------------------------------------------------------------------------
function log_context_set_trace_id() {
    log_context_set "trace_id" "$1"
}

#-----------------------------------------------------------------------------
# 函数: 获取追踪ID
# 参数: 无
# 返回: 输出追踪ID
#-----------------------------------------------------------------------------
function log_context_get_trace_id() {
    log_context_get "trace_id"
}

#-----------------------------------------------------------------------------
# 函数: 生成新的追踪ID
# 参数: $1 - 前缀(可选,默认"trace")
# 返回: 输出生成的追踪ID并设置到上下文
#-----------------------------------------------------------------------------
function log_context_generate_trace_id() {
    local prefix="${1:-trace}"
    local timestamp=$(date +%s)
    local random=$RANDOM
    local trace_id="${prefix}-${timestamp}-${random}"
    
    log_context_set_trace_id "$trace_id"
    echo "$trace_id"
}

#-----------------------------------------------------------------------------
# 函数: 设置会话ID
# 参数: $1 - 会话ID
# 返回: 0-成功
#-----------------------------------------------------------------------------
function log_context_set_session_id() {
    log_context_set "session_id" "$1"
}

#-----------------------------------------------------------------------------
# 函数: 获取会话ID
# 参数: 无
# 返回: 输出会话ID
#-----------------------------------------------------------------------------
function log_context_get_session_id() {
    log_context_get "session_id"
}

#-----------------------------------------------------------------------------
# 函数: 设置请求ID
# 参数: $1 - 请求ID
# 返回: 0-成功
#-----------------------------------------------------------------------------
function log_context_set_request_id() {
    log_context_set "request_id" "$1"
}

#-----------------------------------------------------------------------------
# 函数: 获取请求ID
# 参数: 无
# 返回: 输出请求ID
#-----------------------------------------------------------------------------
function log_context_get_request_id() {
    log_context_get "request_id"
}

#-----------------------------------------------------------------------------
# 函数: 批量设置上下文
# 参数: key1=value1 key2=value2 ...
# 返回: 0-成功
#-----------------------------------------------------------------------------
function log_context_set_batch() {
    for kv in "$@"; do
        if [[ "$kv" =~ ^([^=]+)=(.*)$ ]]; then
            local key="${BASH_REMATCH[1]}"
            local value="${BASH_REMATCH[2]}"
            log_context_set "$key" "$value"
        fi
    done
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 获取所有上下文(JSON格式)
# 参数: 无
# 返回: 输出JSON格式的所有上下文
#-----------------------------------------------------------------------------
function log_context_to_json() {
    local json="{"
    local first=true
    
    for key in "${!_LOG_CONTEXT_DATA[@]}"; do
        if [[ "$first" == true ]]; then
            first=false
        else
            json+=","
        fi
        
        local value="${_LOG_CONTEXT_DATA[$key]}"
        # 简单转义
        value="${value//\\/\\\\}"
        value="${value//\"/\\\"}"
        json+="\"$key\":\"$value\""
    done
    
    json+="}"
    echo "$json"
}

#-----------------------------------------------------------------------------
# 函数: 从环境变量加载上下文
# 参数: 无
# 返回: 0-成功
# 说明: 自动加载LOG_开头的环境变量到上下文
#-----------------------------------------------------------------------------
function log_context_load_from_env() {
    # 遍历所有环境变量
    while IFS='=' read -r -d '' key value; do
        # 只处理LOG_开头的变量
        if [[ "$key" == LOG_* ]]; then
            # 移除LOG_前缀,转小写
            local context_key="${key#LOG_}"
            context_key="${context_key,,}"
            log_context_set "$context_key" "$value"
        fi
    done < <(env -0 2>/dev/null || env | tr '\n' '\0')
    
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 获取调用栈信息
# 参数: $1 - 深度偏移(可选,默认2)
# 返回: 输出调用栈信息
#-----------------------------------------------------------------------------
function log_context_get_callstack() {
    local offset="${1:-2}"
    local stack_info=""
    
    # 获取调用栈
    for ((i=offset; i<${#BASH_SOURCE[@]}; i++)); do
        local source="${BASH_SOURCE[$i]}"
        local line="${BASH_LINENO[$i-1]}"
        local func="${FUNCNAME[$i]}"
        
        if [[ -n "$stack_info" ]]; then
            stack_info+=" <- "
        fi
        stack_info+="$(basename "$source"):$line:$func"
    done
    
    echo "$stack_info"
}

#-----------------------------------------------------------------------------
# 函数: 打印所有上下文(调试用)
# 参数: 无
# 返回: 无
#-----------------------------------------------------------------------------
function log_context_dump() {
    echo "=== 日志上下文信息 ==="
    
    if [[ ${#_LOG_CONTEXT_DATA[@]} -eq 0 ]]; then
        echo "  (空)"
        return 0
    fi
    
    for key in "${!_LOG_CONTEXT_DATA[@]}"; do
        echo "  $key = ${_LOG_CONTEXT_DATA[$key]}"
    done
}

#-----------------------------------------------------------------------------
# 测试函数
#-----------------------------------------------------------------------------
function _log_context_test() {
    echo "=== 上下文管理模块测试 ==="
    
    echo ""
    echo "1. 初始化上下文:"
    _log_context_init
    echo "  ✓ 上下文初始化成功"
    log_context_dump
    
    echo ""
    echo "2. 设置自定义上下文:"
    log_context_set "user_id" "12345"
    log_context_set "tenant_id" "tenant-001"
    log_context_set "module" "auth"
    echo "  ✓ 设置成功"
    
    echo ""
    echo "3. 获取上下文值:"
    echo "  user_id = $(log_context_get user_id)"
    echo "  tenant_id = $(log_context_get tenant_id)"
    echo "  不存在的key = $(log_context_get nonexistent 'default_value')"
    
    echo ""
    echo "4. 生成追踪ID:"
    local trace_id=$(log_context_generate_trace_id "req")
    echo "  生成的trace_id = $trace_id"
    echo "  获取trace_id = $(log_context_get_trace_id)"
    
    echo ""
    echo "5. 批量设置上下文:"
    log_context_set_batch "action=login" "ip=192.168.1.100" "method=POST"
    echo "  ✓ 批量设置成功"
    
    echo ""
    echo "6. 导出为JSON:"
    echo "  $(log_context_to_json)"
    
    echo ""
    echo "7. 获取调用栈:"
    echo "  $(log_context_get_callstack)"
    
    echo ""
    echo "8. 所有上下文:"
    log_context_dump
    
    echo ""
    echo "9. 清除上下文:"
    log_context_clear
    echo "  ✓ 清除成功"
    log_context_dump
}

# 如果直接执行此脚本,运行测试
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    _log_context_test
fi

